<!DOCTYPE html>

<!--
###############################################################################
# Copyright (c) 2011, Vadim Shlyakhov
#
#  Permission is hereby granted, free of charge, to any person obtaining a
#  copy of this software and associated documentation files (the "Software"),
#  to deal in the Software without restriction, including without limitation
#  the rights to use, copy, modify, merge, publish, distribute, sublicense,
#  and/or sell copies of the Software, and to permit persons to whom the
#  Software is furnished to do so, subject to the following conditions:
#
#  The above copyright notice and this permission notice shall be included
#  in all copies or substantial portions of the Software.
#
#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
#  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
#  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
#  DEALINGS IN THE SOFTWARE.
###############################################################################
-->

<html>
<head>
<title>tiles-gmaps</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

<style type="text/css">
  html { height: 100% }
  body { height: 100%; margin: 0px; padding: 0px }
  #map_canvas { height: 100% }
</style>

<script src="http://webpjs.appspot.com/js/webpjs-0.0.2.min.js"></script>

<script src="http://maps.google.com/maps/api/js?sensor=false"> </script>

<script type="text/javascript">
    var G=google.maps; // use G. instead of google.maps.
    var map_type = G.MapTypeId.SATELLITE;
    var opacity = 1;
    var transparent_url='http://maps.gstatic.com/mapfiles/transparent.png';

    function log(msg) {
        try { console.log(msg) }
        catch (e) {
            setTimeout(function() {
                throw new Error(msg);
            }, 0);
        }
    }

    function error(msg) {
        alert(msg);
        throw new Error(msg);
    }

    /*
       Provide the XMLHttpRequest constructor for Internet Explorer 5.x-6.x:
       Other browsers (including Internet Explorer 7.x-9.x) do not redefine
       XMLHttpRequest if it already exists.

       This example is based on findings at:
       http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
    */
    if (typeof XMLHttpRequest == "undefined")
      XMLHttpRequest = function () {
        try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
          catch (e) {}
        try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
          catch (e) {}
        try { return new ActiveXObject("Microsoft.XMLHTTP"); }
          catch (e) {}
        //Microsoft.XMLHTTP points to Msxml2.XMLHTTP and is redundant
        throw new Error("This browser does not support XMLHttpRequest.");
      };

       function read_text(url,mime) {
            var request = new XMLHttpRequest();
            request.open('GET', url, false);
            request.overrideMimeType(mime);
            /*
            request.onreadystatechange = function() {
                log('this.readyState',this.readyState);
                if(this.readyState == 4) {
                  alert("Loaded xml.\nresponseXml: " + xmlhttp.responseXML);
                    }
                }
              */
            try {
                request.send();
                if (request.status != 0) {
                    log('######################### request.status',request.status,request.responseText);
                }
            } catch (e) {
                log('######################### e.code',e.code);
                if (e.code == 101) {
                    error('Google Chrome requires to run with "--allow-file-access-from-files" switch to load XML from local files')
                }
            }
            return request.responseText;
        }

        function read_tilemap() {
            var tilemap_txt=read_text("tilemap.json","application/json");
            if (tilemap_txt == null) {
                error('Cannot read tilemap.json');
                return null;
            };

            var tilemap = JSON.parse(tilemap_txt);

            if (tilemap.type != 'TileMap') {
                error('tilemap.json: incorrect format');
                return null;
            };

            if (tilemap.crs.properties.name != 'EPSG:3857') {
                error('tilemap.json: unsupported CRS');
                return null;
            };

            /*
            if (tilemap.getElementsByTagName("TileSets").length == 0) {
                log(navigator.appName);
                if (navigator.appName == 'Opera')
                    error('tilemap.xml is incorrect. \nYou may need to set "Allow File XMLHttpRequest" with opera:config#UserPrefs|AllowFileXMLHttpRequest to disable this security check.');
                else
                    error('tilemap.xml is incorrect');
                return null;
            }

            var tileset_el_lst=tilemap.getElementsByTagName("TileSet");
            layer_resolutions=[];
            min_res = Number.MAX_VALUE;
            max_res = 0;
            for (i=0; i<tileset_el_lst.length; i++) {
                var zoom = parseInt(tileset_el_lst[i].getAttribute('order'));
                var res = parseFloat(tileset_el_lst[i].getAttribute('units-per-pixel'));
                layer_resolutions[i]=res;
                min_res=Math.min(min_res,res);
                max_res=Math.max(max_res,res);
                tileset_lst[zoom] = {
                    prefix: tileset_el_lst[i].getAttribute('href'),
                    units_per_pixel: res,
                };
            }
            */

            return tilemap;
        }

    function coord2latlong(point) {
        var R = 6378137 // Eatrh's radius as per EPSG:3857
        var lon = 180/Math.PI * (point.x/R);
        var lat = 180/Math.PI * (2*Math.atan(Math.exp(point.y/R)) - Math.PI/2);
        //log('x,y '+point.x+' '+point.y+' lon,lat '+lon+' '+lat);
        return new G.LatLng(lat,lon);
    }
    function opacity_str(opacity){
        var s = String(Math.round(opacity*100));
        while (s.length < 3) s = '+' + s;
        return '<++' + s + '%+++>';
        }

    function opacity_control(map,overlay_index,tilemap) {
        var controlDiv=document.createElement('DIV');
        // Set CSS styles for the DIV containing the control
        // Setting padding will offset the control from the edge of the map
        controlDiv.style.padding = '7px';
        controlDiv.id = 'op-control-div';

        // Set CSS for the control border
        var controlUI = document.createElement('DIV');
        controlUI.style.backgroundColor = 'white';
        controlUI.style.borderStyle = 'solid';
        controlUI.style.borderWidth = '1px';
        controlUI.style.cursor = 'pointer';
        controlUI.style.textAlign = 'center';
        controlUI.title = 'Click to set opacity of the overlay';
        controlUI.id = 'op-control';
        controlDiv.appendChild(controlUI);

        // Set CSS for the control interior
        var controlText = document.createElement('DIV');
        controlText.style.fontFamily = 'monospace';
        controlText.style.fontSize = '10px';
        controlText.style.paddingLeft = '4px';
        controlText.style.paddingRight = '4px';
        controlText.innerHTML = opacity_str(opacity);
        controlText.id = 'op-control-txt';
        controlUI.appendChild(controlText);

        G.event.addDomListener(controlText, 'click', function(event) {
            var rect=controlText.getBoundingClientRect();
            var margin=7
            var w=rect.right-rect.left+1-margin*2;
            var offx=Math.round(event.clientX-rect.left-margin);

            opacity=offx/w; // global
            if (opacity < 0) opacity=0;
            if (opacity > 1) opacity=1;
            controlText.innerHTML = opacity_str(opacity);
            map.overlayMapTypes.removeAt(overlay_index);
            map.overlayMapTypes.insertAt(overlay_index,map_overlay(tilemap));
            });
        return controlDiv;
        }

    function map_overlay(tilemap){

        return new G.ImageMapType({
            opacity: opacity,
            isPng: (tilemap.tiles.ext == "png"),
            tileSize: new G.Size(
                tilemap.tiles.size[0],
                tilemap.tiles.size[1]),

            getTileUrl: function(tile_coord, zoom) {
                var max_x=1<<zoom;
                var max_y=1<<zoom;
                /*
                if (typeof tileset_lst[zoom] == "undefined" ||
                    tile_coord.y >= max_y || tile_coord.y < 0)
                        return transparent_url;
                */
                var y=tile_coord.y;
                if (!tilemap.tiles.inversion[1]) {
                    y= -y -1;
                    y += max_y;
                }
                var x=tile_coord.x % max_x;
                if (x < 0)
                    x=max_x+x;
                var url = 'z'+zoom+"/"+y+"/"+x+"."+tilemap.tiles.ext;
                //log(url);
                return url;
                }
            })
        }

    function initialize() {
        var map = new G.Map(document.getElementById("map_canvas"));
        var tilemap=read_tilemap();
        document.title = tilemap.properties.title;

        var box_sw=coord2latlong(new G.Point(tilemap.bbox[0],tilemap.bbox[1]));
        var box_ne=coord2latlong(new G.Point(tilemap.bbox[2],tilemap.bbox[3]));

        map.fitBounds(new G.LatLngBounds(box_sw, box_ne));
        map.setMapTypeId(map_type);

        var layer=map_overlay(tilemap);
        //log(layer);
        var overlay_index=map.overlayMapTypes.push(layer) - 1;
        map.controls[G.ControlPosition.TOP_RIGHT].push(opacity_control(map,overlay_index,tilemap));
        }
</script>
</head>

<body onload="initialize()">
    <div id="map_canvas" style="width:100%; height:100%"></div>
</body>
</html>
